/*
* Copyright 2016 Yonyou Auto Information Technology（Shanghai） Co., Ltd. All Rights Reserved.
*
* This software is published under the terms of the YONYOU Software
* License version 1.0, a copy of which has been included with this
* distribution in the LICENSE.txt file.
*
* @Project Name : marketing-service-user
*
* @File name : OAuthService.java
*
* @Author : WangHuicheng
*
* @Date : 2016年12月15日
*
----------------------------------------------------------------------------------
*     Date              Who             Version     Comments
* 1.  2016年12月15日    WangHuicheng    1.0
*
*
*
*
----------------------------------------------------------------------------------
*/

package com.yonyou.gmmc.dealerApp.api.service;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.marketing.common.constants.AppCode;
import org.marketing.common.dto.user.AccessTokenDto;
import org.marketing.common.dto.user.TM_UsersDto;
import org.marketing.common.exception.ServiceAppException;
import org.marketing.common.exception.ServiceBizException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yonyou.gmmc.dealerApp.api.dao.TtDealerappLoginTokenMapper;
import com.yonyou.gmmc.dealerApp.api.entity.AccessTokenPO;

/**
 * 登录认证Service
 * 
 * @author WangHuicheng
 * @date 2016年12月15日
 */
@Service("oAuthService")
public class OAuthService {

    private Logger         logger        = Logger.getLogger(OAuthService.class);

    private Long           defaultExpire = 30 * 24 * 3600l * 1000;
    @Autowired
    private TtDealerappLoginTokenMapper accessTokenDao;

    /**
     * 取得TOKEN值
     *
     * @author WangHuicheng
     * @date 2016年12月15日
     * @param user
     * @return
     * @throws Exception
     */
    public AccessTokenDto genAccessToken(TM_UsersDto user) throws ServiceAppException, ServiceBizException {
        this.logger.info("为用户获取token开始" + user.getUserId());
        // 保存用户AccessToken
        // 默认过期时间为
        AccessTokenDto accessToken = new AccessTokenDto();
        accessToken.setAccessToken(UUID.randomUUID().toString().replace("-", ""));
        accessToken.setExpire(defaultExpire);
        this.logger.info("为用户获取token结束：token：" + accessToken.getAccessToken());
        return accessToken;
    }

    /**
     * 刷新登录用户的TOKEN
     * 
     * @author WangHuicheng
     * @date 2016年12月15日
     * @param user
     * @return
     * @throws Exception
     */
    public AccessTokenDto refreshAccessToken(TM_UsersDto user) throws ServiceAppException, ServiceBizException {

        // 删除用户的TOKEN信息
        accessTokenDao.deleteAccesToken(user.getUserId());

        // 插入新的TOKEN信息
        AccessTokenDto accessToken = genAccessToken(user);
        
        AccessTokenPO accessTokenPO = new AccessTokenPO();
        accessTokenPO.setAccessToken(accessToken.getAccessToken());
        accessTokenPO.setUsersId(user.getUserId());
        accessTokenPO.setExpireDate(new Date());
        accessTokenPO.setCreateBy(user.getUserId());
        accessTokenPO.setCreateDate(new Date());
        // 保存token信息
        Long id = accessTokenDao.saveToken(accessTokenPO);
        
        accessToken.setExpireDate(accessTokenPO.getExpireDate());
        accessToken.setUsersId(user.getUserId());
        accessToken.setDealerappLoginTokenId(id);
        accessToken.setExpireDate(accessTokenPO.getExpireDate());
        return accessToken;
    }

    /**
     * 保存TOKEN
     * 
     * @author WangHuicheng
     * @date 2016年12月15日
     * @param accessTokenPO
     * @return
     */
    public Long saveToken(AccessTokenPO accessTokenPO) {
        return accessTokenDao.saveToken(accessTokenPO);
    }

    /**
     * 检查TOKEN的期限
     *
     * @author WangHuicheng
     * @date 2016年12月16日
     * @param user
     * @param accessToken
     * @throws Exception
     */
    public void checkAccessTokenExpire(TM_UsersDto user, String accessToken) throws ServiceAppException,
                                                                             ServiceBizException {

        AccessTokenDto vo = loadAccessToken(user);

        if (!StringUtils.equals(vo.getAccessToken(), accessToken)
            /*|| new Date(vo.getExpire()).compareTo(new Date()) < 0*/) {
            throw new ServiceBizException(AppCode.APP_ACCESS_TOKEN_INVALID);
        }
    }

    /**
     * 加载AccessToken
     * 
     * @author WangHuicheng
     * @date 2016年12月16日
     * @param user
     * @return
     * @throws ServiceAppException
     * @throws ServiceBizException
     */
    private AccessTokenDto loadAccessToken(TM_UsersDto user) throws ServiceAppException, ServiceBizException {
        try {
            AccessTokenDto accessTokenDto = new AccessTokenDto();
            accessTokenDto.setUsersId(user.getUserId());
            List<AccessTokenDto> list = accessTokenDao.loadAccessToken(accessTokenDto);
            if (list != null && list.size() > 0) {
                return list.get(0);
            } else {
                return null;
            }
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
            throw new ServiceAppException(e.getMessage(), e);
        }
    }

    /**
     * 加载AccessToken
     *
     * @author WangHuicheng
     * @date 2016年12月16日
     * @param accessToken
     * @return
     * @throws ServiceAppException
     * @throws ServiceBizException
     */
    private AccessTokenDto loadAccessToken(String accessToken) throws ServiceAppException, ServiceBizException {
        try {
            AccessTokenDto accessTokenDto = new AccessTokenDto();
            accessTokenDto.setAccessToken(accessToken);
            List<AccessTokenDto> list = accessTokenDao.loadAccessToken(accessTokenDto);
            if (list != null && list.size() > 0) {
                return list.get(0);
            } else {
                return null;
            }
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
            throw new ServiceAppException(e.getMessage(), e);
        }
    }

    /**
     * 判断 userId 和 token 是否一致
     * 
     * @author WangHuicheng
     * @date 2016年12月16日
     * @param userId
     * @param token
     * @return
     */
    public boolean isExist(Long userId, String token) {
        AccessTokenDto accessTokenDto = new AccessTokenDto();
        accessTokenDto.setUsersId(userId);
        accessTokenDto.setAccessToken(token);
        List<AccessTokenDto> list = accessTokenDao.loadAccessToken(accessTokenDto);
        if (list.isEmpty()) {
            return true;
        }
        return false;
    }

    /**
     * 判断 userId 和 token 是否一致
     * 
     * @author WangHuicheng
     * @date 2016年12月16日
     * @param accessToken
     * @param userId
     * @throws ServiceAppException
     * @throws ServiceBizException
     */
    public void checkAccessTokenExpire(String accessToken, Long userId) throws ServiceAppException,
                                                                          ServiceBizException {
        try {

            AccessTokenDto vo = loadAccessToken(accessToken);
            if (null == vo) {
                throw new ServiceAppException(AppCode.APP_ACCESS_TOKEN_INVALID_CODE);
            }

            if (!StringUtils.equals(vo.getAccessToken(), accessToken)
                /*|| new Date(vo.getExpire()).compareTo(new Date()) < 0*/) {
                throw new Exception(AppCode.APP_ACCESS_TOKEN_INVALID_CODE);
            }

            if (null != userId) {
                boolean flag = isExist(userId, accessToken);
                logger.info("true: token失效; false: 正常登陆 。flag ====== " + flag);
                if (flag) {
                    throw new ServiceAppException(AppCode.APP_ACCESS_TOKEN_INVALID_CODE);
                }
            }

        } catch (Throwable t) {
            logger.error("checkAccessTokenExpire error,cause:" + t.getMessage(), t);
            throw new ServiceAppException(AppCode.APP_ACCESS_TOKEN_INVALID_CODE);
        }
    }

    /**
     * 取得发生日期
     * 
     * @author WangHuicheng
     * @date 2016年12月16日
     * @param accessToken
     * @return
     */
    public AccessTokenDto getExpireDate(String accessToken) {
        try {
            AccessTokenDto accessTokenDto = new AccessTokenDto();
            accessTokenDto.setAccessToken(accessToken);
            List<AccessTokenDto> list = this.accessTokenDao.loadAccessToken(accessTokenDto);

            if (list != null && list.size() > 0) {
                return list.get(0);
            } else {
                return null;
            }
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
            throw new ServiceAppException(e.getMessage(), e);
        }
    }

}
